# 整体框架
对于 Binderized HALs,HAL 层以进程的形式存在,内部有一个 HwBinder 服务端对象,对外提供 HwBinder 远程调用服务。Framework 通过 HwBinder 远程调用到 HAL 中的函数,这些函数直接访问具体的驱动。
在源码下 device/google/coral/vibrator/
目录下,是 Google 为 pixel4、pixel4 xl 实现的振动器 HAL,其类型就是 Binderized HALs。本文分析其具体实现.
# HAL 层服务端实现
HAL 层表现为一个进程:
进程对应的代码位于 device/google/coral/vibrator
整体结构如下:
我们从 Android.bp 下手:
cc_defaults {
name: "android.hardware.vibrator@1.3-defaults.coral",
defaults: ["hidl_defaults"],
relative_install_path: "hw",
shared_libs: [
"libhidlbase",
"libcutils",
"libhidltransport",
"liblog",
"libhwbinder",
"libutils",
"libhardware",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
"android.hardware.vibrator@1.3",
],
}
cc_defaults {
name: "PtsVibratorHalFloralDefaults",
defaults: ["android.hardware.vibrator@1.3-defaults.coral"],
static_libs: ["android.hardware.vibrator@1.3-impl.coral"],
test_suites: [
"general-tests",
"pts",
],
multilib: {
lib32: {
suffix: "32",
},
lib64: {
suffix: "64",
},
},
}
cc_library {
name: "android.hardware.vibrator@1.3-impl.coral",
defaults: ["android.hardware.vibrator@1.3-defaults.coral"],
srcs: [
"Hardware.cpp",
"Vibrator.cpp",
],
export_include_dirs: ["."],
vendor_available: true,
}
cc_binary {
name: "android.hardware.vibrator@1.3-service.coral",
defaults: ["android.hardware.vibrator@1.3-defaults.coral"],
init_rc: ["android.hardware.vibrator@1.3-service.coral.rc"],
vintf_fragments: ["android.hardware.vibrator@1.3-service.coral.xml"],
srcs: ["service.cpp"],
static_libs: ["android.hardware.vibrator@1.3-impl.coral"],
proprietary: true,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
一个共享库 android.hardware.vibrator@1.3-impl.coral
,一个 native 可执行程序 android.hardware.vibrator@1.3-service.coral
。
android.hardware.vibrator@1.3-impl.coral
共享库中 :
- Hardware.cpp 中对振动器驱动的访问包装成了两个对象 HwApi HwCal。
- Vibrator.cpp 链接了
android.hardware.vibrator@1.3
库,内部有一个 Vibrator类,继承自android.hardware.vibrator@1.3
库中 IVibrator,IVibrator 是由hardware/interfaces/vibrator/1.3/IVibrator.hal
编译出来的。Vibrator 类是一个 HwBinder 服务端类,对外提供了调用振动器的接口,内部实现是通过调用 HwApi HwCal 对象的成员函数实现的。
android.hardware.vibrator@1.3-service.coral
可执行程序:
status_t registerVibratorService() {
sp<Vibrator> vibrator = new Vibrator(std::make_unique<HwApi>(), std::make_unique<HwCal>());
return vibrator->registerAsService();
}
int main() {
configureRpcThreadpool(1, true);
status_t status = registerVibratorService();
if (status != OK) {
return status;
}
joinRpcThreadpool();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
实现上很简单:
- 向 HwServiceManager 注册 Vibrator
- 配置 HwBinder 线程
具体振动器的操作细节就不看了,这不是我们的重点。
# Framework 层客户端实现
对于客户端,我们只要知道 Hal 对外提供的接口即可,这个接口又 hardware/interfaces/vibrator/1.3/IVibrator.hal
描述:
package android.hardware.vibrator@1.3;
import @1.0::EffectStrength;
import @1.0::Status;
import @1.2::IVibrator;
interface IVibrator extends @1.2::IVibrator {
supportsExternalControl() generates (bool supports);
setExternalControl(bool enabled) generates (Status status);
perform_1_3(Effect effect, EffectStrength strength)
generates (Status status, uint32_t lengthMs);
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
frameworks/base/services/core/java/com/android/server/VibratorService.java
本身是一个 Binder 服务端向 App 提供服务,同时也是一个 HwBinder 客户端通过 JNI 访问到 HAL 服务端。
public class VibratorService extends IVibratorService.Stub
implements InputManager.InputDeviceListener {
// ......
static native boolean vibratorExists();
static native void vibratorInit();
static native void vibratorOn(long milliseconds);
static native void vibratorOff();
static native boolean vibratorSupportsAmplitudeControl();
static native void vibratorSetAmplitude(int amplitude);
static native long vibratorPerformEffect(long effect, long strength);
static native boolean vibratorSupportsExternalControl();
static native void vibratorSetExternalControl(boolean enabled);
// ......
}
2
3
4
5
6
7
8
9
10
11
12
13
14
VibratorService 中有多个 native 方法,这些方法用于远程调用 Hal 层。
对应的 JNI 函数实现在 frameworks/base/services/core/jni/com_android_server_VibratorService.cpp
:
#define LOG_TAG "VibratorService"
#include <android/hardware/vibrator/1.0/IVibrator.h>
#include <android/hardware/vibrator/1.0/types.h>
#include <android/hardware/vibrator/1.0/IVibrator.h>
#include <android/hardware/vibrator/1.1/types.h>
#include <android/hardware/vibrator/1.2/IVibrator.h>
#include <android/hardware/vibrator/1.2/types.h>
#include <android/hardware/vibrator/1.3/IVibrator.h>
#include "jni.h"
#include <nativehelper/JNIHelp.h>
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/vibrator.h>
#include <inttypes.h>
#include <stdio.h>
using android::hardware::Return;
using android::hardware::vibrator::V1_0::EffectStrength;
using android::hardware::vibrator::V1_0::Status;
using android::hardware::vibrator::V1_1::Effect_1_1;
namespace V1_0 = android::hardware::vibrator::V1_0;
namespace V1_1 = android::hardware::vibrator::V1_1;
namespace V1_2 = android::hardware::vibrator::V1_2;
namespace V1_3 = android::hardware::vibrator::V1_3;
namespace android {
static constexpr int NUM_TRIES = 2;
// Creates a Return<R> with STATUS::EX_NULL_POINTER.
template<class R>
inline Return<R> NullptrStatus() {
using ::android::hardware::Status;
return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)};
}
// Helper used to transparently deal with the vibrator HAL becoming unavailable.
template<class R, class I, class... Args0, class... Args1>
Return<R> halCall(Return<R> (I::* fn)(Args0...), Args1&&... args1) {
// Assume that if getService returns a nullptr, HAL is not available on the
// device.
static sp<I> sHal = I::getService();
static bool sAvailable = sHal != nullptr;
if (!sAvailable) {
return NullptrStatus<R>();
}
// Return<R> doesn't have a default constructor, so make a Return<R> with
// STATUS::EX_NONE.
using ::android::hardware::Status;
Return<R> ret{Status::fromExceptionCode(Status::EX_NONE)};
// Note that ret is guaranteed to be changed after this loop.
for (int i = 0; i < NUM_TRIES; ++i) {
ret = (sHal == nullptr) ? NullptrStatus<R>()
: (*sHal.*fn)(std::forward<Args1>(args1)...);
if (ret.isOk()) {
break;
}
ALOGE("Failed to issue command to vibrator HAL. Retrying.");
// Restoring connection to the HAL.
sHal = I::tryGetService();
}
return ret;
}
template<class R>
bool isValidEffect(jlong effect) {
if (effect < 0) {
return false;
}
R val = static_cast<R>(effect);
auto iter = hardware::hidl_enum_range<R>();
return val >= *iter.begin() && val <= *std::prev(iter.end());
}
static void vibratorInit(JNIEnv /* env */, jobject /* clazz */)
{
halCall(&V1_0::IVibrator::ping).isOk();
}
static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */)
{
return halCall(&V1_0::IVibrator::ping).isOk() ? JNI_TRUE : JNI_FALSE;
}
static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms)
{
Status retStatus = halCall(&V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR);
if (retStatus != Status::OK) {
ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
}
}
static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */)
{
Status retStatus = halCall(&V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR);
if (retStatus != Status::OK) {
ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
}
}
static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jobject) {
return halCall(&V1_0::IVibrator::supportsAmplitudeControl).withDefault(false);
}
static void vibratorSetAmplitude(JNIEnv*, jobject, jint amplitude) {
Status status = halCall(&V1_0::IVibrator::setAmplitude, static_cast<uint32_t>(amplitude))
.withDefault(Status::UNKNOWN_ERROR);
if (status != Status::OK) {
ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").",
static_cast<uint32_t>(status));
}
}
static jboolean vibratorSupportsExternalControl(JNIEnv*, jobject) {
return halCall(&V1_3::IVibrator::supportsExternalControl).withDefault(false);
}
static void vibratorSetExternalControl(JNIEnv*, jobject, jboolean enabled) {
Status status = halCall(&V1_3::IVibrator::setExternalControl, static_cast<uint32_t>(enabled))
.withDefault(Status::UNKNOWN_ERROR);
if (status != Status::OK) {
ALOGE("Failed to set vibrator external control (%" PRIu32 ").",
static_cast<uint32_t>(status));
}
}
static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength) {
Status status;
uint32_t lengthMs;
auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) {
status = retStatus;
lengthMs = retLengthMs;
};
EffectStrength effectStrength(static_cast<EffectStrength>(strength));
Return<void> ret;
if (isValidEffect<V1_0::Effect>(effect)) {
ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect),
effectStrength, callback);
} else if (isValidEffect<Effect_1_1>(effect)) {
ret = halCall(&V1_1::IVibrator::perform_1_1, static_cast<Effect_1_1>(effect),
effectStrength, callback);
} else if (isValidEffect<V1_2::Effect>(effect)) {
ret = halCall(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(effect),
effectStrength, callback);
} else if (isValidEffect<V1_3::Effect>(effect)) {
ret = halCall(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(effect),
effectStrength, callback);
} else {
ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")",
static_cast<int32_t>(effect));
return -1;
}
if (!ret.isOk()) {
ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect));
return -1;
}
if (status == Status::OK) {
return lengthMs;
} else if (status != Status::UNSUPPORTED_OPERATION) {
// Don't warn on UNSUPPORTED_OPERATION, that's a normal event and just means the motor
// doesn't have a pre-defined waveform to perform for it, so we should just give the
// opportunity to fall back to the framework waveforms.
ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32
", error=%" PRIu32 ").", static_cast<int64_t>(effect),
static_cast<int32_t>(strength), static_cast<uint32_t>(status));
}
return -1;
}
static const JNINativeMethod method_table[] = {
{ "vibratorExists", "()Z", (void*)vibratorExists },
{ "vibratorInit", "()V", (void*)vibratorInit },
{ "vibratorOn", "(J)V", (void*)vibratorOn },
{ "vibratorOff", "()V", (void*)vibratorOff },
{ "vibratorSupportsAmplitudeControl", "()Z", (void*)vibratorSupportsAmplitudeControl},
{ "vibratorSetAmplitude", "(I)V", (void*)vibratorSetAmplitude},
{ "vibratorPerformEffect", "(JJ)J", (void*)vibratorPerformEffect},
{ "vibratorSupportsExternalControl", "()Z", (void*)vibratorSupportsExternalControl},
{ "vibratorSetExternalControl", "(Z)V", (void*)vibratorSetExternalControl},
};
int register_android_server_VibratorService(JNIEnv *env)
{
return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
method_table, NELEM(method_table));
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
所有的函数都通过 hascall 来实现,hascall 中会去从 HwServiceManager 中去获取 Vibrator Hal 的代理对象,然后通过这个代理对象发起远程调用,从而调用到 HAL 层。
最后我们再来看 HAL 端的 vintf 配置文件 /home/zzh0838/Project/android-10.0.0_r41/device/google/coral/vibrator/android.hardware.vibrator@1.3-service.coral.xml
:
<manifest version="1.0" type="device">
<hal format="hidl">
<name>android.hardware.vibrator</name>
<transport>hwbinder</transport>
<version>1.3</version>
<interface>
<name>IVibrator</name>
<instance>default</instance>
</interface>
</hal>
</manifest>
2
3
4
5
6
7
8
9
10
11
注意这里 transport 指定了 hal 的类型为 hwbinder,也就是我们说的 Binderized hal。